package qeug.shsh.opplugin;

import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.entity.datamodel.events.PropertyChangedArgs;
import kd.bos.form.control.Control;
import kd.bos.form.control.Label;
import kd.bos.form.events.BeforeDoOperationEventArgs;
import kd.bos.form.operate.FormOperate;
import kd.bos.form.plugin.AbstractFormPlugin;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.Calendar;
import java.util.Date;
import java.util.EventObject;

/**
 * @projectName: qeug-cosmic-root-project
 * @package: qeug.shsh.opplugin
 * @className: TravelBillPlugin
 * @author: xuhaihui
 * @description: 差旅报销单表单插件
 * @date: 2024/3/1
 * @version: 1.0
 * //说明：计算误餐补贴中补贴餐数，餐补金额字段；是否含早的字段逻辑
 */
public class TravelBillPlugin extends AbstractFormPlugin {

    private static final int MORNING_HOUR = 8;
    private static final int NOON_HOUR = 12;
    private static final int EVENING_HOUR = 17;

    @Override
    public void registerListener(EventObject e) {
        super.registerListener(e);
        Label delexpense = this.getControl("delexpense");//差旅明细删除标签
        delexpense.addClickListener(this);
    }

    @Override
    public void click(EventObject evt) {
        super.click(evt);
        Control source = (Control) evt.getSource();
        String key = source.getKey();
        if ("delexpense".equals(key)) {
            DynamicObjectCollection tripEntries = this.getModel().getEntryEntity("tripentry"); // 行程信息分录
            setMeals2(tripEntries);
            this.getView().updateView("entryentity"); // 差旅明细
        }
    }

    @Override
    public void propertyChanged(PropertyChangedArgs e) {
        super.propertyChanged(e);
        String fieldKey = e.getProperty().getName();
        if ("startdate".equals(fieldKey) || "enddate".equals(fieldKey) || "expenseitem".equals(fieldKey) ||
                "caldaycount".equals(fieldKey) || "qeug_checkboxfield".equals(fieldKey) || "istravelers".equals(fieldKey)) {
            // 开始时间、结束时间、差旅项目、标准天数、是否含早、多出差人
            DynamicObjectCollection tripEntries = this.getModel().getEntryEntity("tripentry");
            setMeals2(tripEntries);
            this.getView().updateView("entryentity"); // 差旅明细
        }
    }

    @Override
    public void afterBindData(EventObject e) {
        DynamicObjectCollection tripEntries = this.getModel().getEntryEntity("tripentry");
        setMeals2(tripEntries);
    }

    @Override
    public void beforeDoOperation(BeforeDoOperationEventArgs args) {
        FormOperate operate = (FormOperate) args.getSource();
        String operateKey = operate.getOperateKey();
        if ("submit".equals(operateKey)) {
            DynamicObjectCollection tripEntries = this.getModel().getEntryEntity("tripentry");
            setMeals2(tripEntries);
        }
    }

    /**
     * 处理是否含早的情况，计算早餐补贴数量
     */
    public void setMeals2(DynamicObjectCollection tripEntries) {
        for (int parentRowIndex = 0; parentRowIndex < tripEntries.size(); parentRowIndex++) {
            DynamicObject tripEntry = tripEntries.get(parentRowIndex);
            DynamicObjectCollection entryEntityCollection = tripEntry.getDynamicObjectCollection("entryentity");

            BigDecimal caldaycounts = BigDecimal.ZERO;
            boolean isCheckboxField = false;

            for (DynamicObject entryEntity : entryEntityCollection) {
                DynamicObject expenseItem = entryEntity.getDynamicObject("expenseitem");
                if (expenseItem != null && "002".equals(expenseItem.getString("number"))) { // 住宿费
                    boolean checkboxField = entryEntity.getBoolean("qeug_checkboxfield"); // 是否含早
                    if (checkboxField) {
                        BigDecimal caldaycount = entryEntity.getBigDecimal("caldaycount"); // 标准天数
                        caldaycounts = caldaycounts.add(caldaycount);
                        isCheckboxField = true;
                    }
                }
            }

            for (int rowIndex = 0; rowIndex < entryEntityCollection.size(); rowIndex++) {
                DynamicObject entryEntity = entryEntityCollection.get(rowIndex);
                BigDecimal decimalField = entryEntity.getBigDecimal("qeug_decimalfield"); // 早餐补贴数
                BigDecimal subtract = decimalField.subtract(caldaycounts);
                this.getModel().setValue("qeug_meals", subtract, rowIndex, parentRowIndex); // 早餐数
            }

            if (!isCheckboxField) {
                setMeals(tripEntries, parentRowIndex); // 不存在含早，重新计算
            }
        }
    }

    /**
     * 主要计算方法，用于计算误餐补贴次数
     */
    public void setMeals(DynamicObjectCollection tripEntries, int parentRowIndex) {
        DynamicObject tripEntry = tripEntries.get(parentRowIndex);
        Date startDate = tripEntry.getDate("startdate");
        Date endDate = tripEntry.getDate("enddate");

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(startDate);
        Calendar endCalendar = Calendar.getInstance();
        endCalendar.setTime(endDate);

        int startHour = calendar.get(Calendar.HOUR_OF_DAY);
        int endHour = endCalendar.get(Calendar.HOUR_OF_DAY);

        LocalDateTime startLocalDateTime = convertToLocalDateTime(startDate);
        LocalDateTime endLocalDateTime = convertToLocalDateTime(endDate);

        long differenceDays = ChronoUnit.DAYS.between(startLocalDateTime.toLocalDate(), endLocalDateTime.toLocalDate());
        double addOneDay = differenceDays + 1;
        double loseOneDay = differenceDays - 1;

        DynamicObjectCollection entryEntity = tripEntry.getDynamicObjectCollection("entryentity");

        if (startHour < MORNING_HOUR) {
            // 开始时间在早上8点之前
            if (endHour < MORNING_HOUR) {
                updateMealFields(entryEntity, parentRowIndex, differenceDays, differenceDays, differenceDays, differenceDays);
            } else if (endHour < NOON_HOUR) {
                updateMealFields(entryEntity, parentRowIndex, addOneDay, addOneDay, differenceDays, differenceDays);
            } else if (endHour < EVENING_HOUR) {
                updateMealFields(entryEntity, parentRowIndex, addOneDay, addOneDay, addOneDay, differenceDays);
            } else {
                updateMealFields(entryEntity, parentRowIndex, addOneDay, addOneDay, addOneDay, addOneDay);
            }

        } else if (startHour < NOON_HOUR) {
            // 开始时间在早上8点到中午12点之间
            if (endHour < MORNING_HOUR) {
                updateMealFields(entryEntity, parentRowIndex, loseOneDay, loseOneDay, differenceDays, differenceDays);
            } else if (endHour < NOON_HOUR) {
                updateMealFields(entryEntity, parentRowIndex, differenceDays, differenceDays, differenceDays, differenceDays);
            } else if (endHour < EVENING_HOUR) {
                updateMealFields(entryEntity, parentRowIndex, differenceDays, differenceDays, addOneDay, differenceDays);
            } else {
                updateMealFields(entryEntity, parentRowIndex, differenceDays, differenceDays, addOneDay, addOneDay);
            }

        } else if (startHour < EVENING_HOUR) {
            // 开始时间在中午12点到下午5点之间
            if (endHour < MORNING_HOUR) {
                updateMealFields(entryEntity, parentRowIndex, loseOneDay, loseOneDay, loseOneDay, differenceDays);
            } else if (endHour < NOON_HOUR) {
                updateMealFields(entryEntity, parentRowIndex, differenceDays, differenceDays, loseOneDay, differenceDays);
            } else if (endHour < EVENING_HOUR) {
                updateMealFields(entryEntity, parentRowIndex, differenceDays, differenceDays, differenceDays, differenceDays);
            } else {
                updateMealFields(entryEntity, parentRowIndex, differenceDays, differenceDays, differenceDays, addOneDay);
            }

        } else {
            // 开始时间在下午5点之后
            if (endHour < MORNING_HOUR) {
                updateMealFields(entryEntity, parentRowIndex, loseOneDay, loseOneDay, loseOneDay, loseOneDay);
            } else if (endHour < NOON_HOUR) {
                updateMealFields(entryEntity, parentRowIndex, differenceDays, differenceDays, loseOneDay, loseOneDay);
            } else if (endHour < EVENING_HOUR) {
                updateMealFields(entryEntity, parentRowIndex, differenceDays, differenceDays, differenceDays, loseOneDay);
            } else {
                updateMealFields(entryEntity, parentRowIndex, differenceDays, differenceDays, differenceDays, differenceDays);
            }
        }
    }

    /**
     * 将 Date 转换为 LocalDateTime
     */
    private LocalDateTime convertToLocalDateTime(Date date) {
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
    }

    /**
     * @param entryEntity    差旅分录
     * @param parentRowIndex 行程信息分录行
     * @param qeugMeals      早餐数1
     * @param qeugDecimal    早餐数2
     * @param qeugMeals2     午餐数
     * @param qeugMeals3     晚餐数
     */
    private void updateMealFields(DynamicObjectCollection entryEntity, int parentRowIndex,
                                  double qeugMeals, double qeugDecimal, double qeugMeals2, double qeugMeals3) {
        for (int b = 0; b < entryEntity.size(); b++) {
            this.getModel().setValue("qeug_meals", qeugMeals, b, parentRowIndex);
            this.getModel().setValue("qeug_decimalfield", qeugDecimal, b, parentRowIndex);
            this.getModel().setValue("qeug_meals2", qeugMeals2, b, parentRowIndex);
            this.getModel().setValue("qeug_meals3", qeugMeals3, b, parentRowIndex);
        }
    }
}
